#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""            
@FileName: regula_falsi.py
@Version: 1.0
@Date: 2023/6/21 10:33
@Description:
"""

import math
from root_paras import Paras


def regula_falsi(fun, paras: Paras = Paras()) -> tuple[float, float, float]:
    sec_tol = paras.sec_tol
    a: float = paras.start
    b: float = paras.end

    if math.fabs(b - a) < sec_tol:
        b = a + paras.dft_sect

    sol_tol = paras.sol_tol
    n: int = 0
    c: float = 0
    loops = paras.loops
    while math.fabs(b - a) > sec_tol:
        n += 1
        if n > loops:
            raise RuntimeError(f'regula-falsi iteration: loop over 1000 times, with interval {b - a}')

        dy: float = fun(b) - fun(a)
        if math.fabs(dy) < sol_tol:
            print(f'regula-falsi method, dy = {dy} ~> 0')

        c = (a * fun(b) - b * fun(a)) / dy
        if math.fabs(fun(c) - 0) <= sol_tol:
            break

        if fun(a) * fun(c) < 0:
            b = c
        else:
            a = c

    if math.fabs((val := fun(c)) - 0) <= sol_tol:
        print(n)
        return c, a, b
    else:
        raise RuntimeError(f'regula-falsi iteration: did not converge to zero, instead -> {val}')


if __name__ == '__main__':
    f = lambda x: x ** 3 + x - 1
    res = regula_falsi(f)
    print(res)
